Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Skovhede <kenneth@hexad.dk>2017-09-23 23:01:08 +0300
committerKenneth Skovhede <kenneth@hexad.dk>2017-09-23 23:01:08 +0300
commit6c921ab3ec878a99262150b80b7f29713700c11e (patch)
tree66a5baf290fa263f122bc9c73a632aeed98c1da9 /Duplicati/Library
parent22e05577e294633f995bd163026437973c61ff55 (diff)
parent60b94b758f01446db6feaea72949833144fce953 (diff)
Merge branch 'master' of github.com:duplicati/duplicati
Diffstat (limited to 'Duplicati/Library')
-rw-r--r--Duplicati/Library/Backend/OneDrive/OneDrive.cs107
-rw-r--r--Duplicati/Library/Interface/IBackend.cs3
-rw-r--r--Duplicati/Library/Interface/IRenameEnabledBackend.cs10
-rw-r--r--Duplicati/Library/Main/Operation/FilelistProcessor.cs4
-rw-r--r--Duplicati/Library/Main/Options.cs9
-rw-r--r--Duplicati/Library/Main/Strings.cs8
6 files changed, 116 insertions, 25 deletions
diff --git a/Duplicati/Library/Backend/OneDrive/OneDrive.cs b/Duplicati/Library/Backend/OneDrive/OneDrive.cs
index 289dd024a..2b85409bb 100644
--- a/Duplicati/Library/Backend/OneDrive/OneDrive.cs
+++ b/Duplicati/Library/Backend/OneDrive/OneDrive.cs
@@ -7,7 +7,7 @@ using Duplicati.Library.Interface;
namespace Duplicati.Library.Backend
{
- public class OneDrive : IBackend, IStreamingBackend
+ public class OneDrive : IBackend, IStreamingBackend, IQuotaEnabledBackend, IRenameEnabledBackend
{
private const string AUTHID_OPTION = "authid";
@@ -73,11 +73,11 @@ namespace Duplicati.Library.Backend
public string upload_location { get; set; }
public string type { get; set; }
[Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
- public DateTime created_time { get; set; }
+ public DateTime? created_time { get; set; }
[Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
- public DateTime updated_time { get; set; }
+ public DateTime? updated_time { get; set; }
[Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
- public long size { get; set; }
+ public long? size { get; set; }
}
private class WLID_CreateFolderData
@@ -106,13 +106,21 @@ namespace Duplicati.Library.Backend
public string locale { get; set; }
}
+ private class WLID_QuotaInfo
+ {
+ [Newtonsoft.Json.JsonProperty("quota")]
+ public long? Quota { get; set; }
+ [Newtonsoft.Json.JsonProperty("available")]
+ public long? Available { get; set; }
+ }
+
private WLID_FolderItem FindFolder(string folder, string parentfolder = null)
{
if (string.IsNullOrWhiteSpace(parentfolder))
parentfolder = ROOT_FOLDER_ID;
var url = string.Format("{0}/{1}?access_token={2}", WLID_SERVER, string.Format(FOLDER_TEMPLATE, parentfolder), Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
- var res = m_oauth.GetJSONData<WLID_DataItem>(url);
+ var res = m_oauth.GetJSONData<WLID_DataItem>(url, x => x.UserAgent = USER_AGENT);
if (res == null || res.data == null)
return null;
@@ -130,7 +138,7 @@ namespace Duplicati.Library.Backend
if (folders.Length == 0)
{
var url = string.Format("{0}/{1}?access_token={2}", WLID_SERVER, ROOT_FOLDER_ID, Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
- return m_oauth.GetJSONData<WLID_FolderItem>(url);
+ return m_oauth.GetJSONData<WLID_FolderItem>(url, x => x.UserAgent = USER_AGENT);
}
WLID_FolderItem cur = null;
@@ -214,6 +222,12 @@ namespace Duplicati.Library.Backend
return id;
}
+ private WLID_QuotaInfo GetQuotaInfo()
+ {
+ var url = string.Format("{0}/me/skydrive/quota?access_token={1}", WLID_SERVER, Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
+ return m_oauth.GetJSONData<WLID_QuotaInfo>(url, x => x.UserAgent = USER_AGENT);
+ }
+
#region IBackend Members
public void Test()
@@ -248,7 +262,7 @@ namespace Duplicati.Library.Backend
while(count == FILE_LIST_PAGE_SIZE)
{
var url = string.Format("{0}/{1}?access_token={2}&limit={3}&offset={4}", WLID_SERVER, string.Format(FOLDER_TEMPLATE, FolderID), Library.Utility.Uri.UrlEncode(m_oauth.AccessToken), FILE_LIST_PAGE_SIZE, offset);
- var res = m_oauth.GetJSONData<WLID_DataItem>(url);
+ var res = m_oauth.GetJSONData<WLID_DataItem>(url, x => x.UserAgent = USER_AGENT);
if (res != null && res.data != null)
{
@@ -257,7 +271,7 @@ namespace Duplicati.Library.Backend
{
m_fileidCache.Add(r.name, r.id);
- var fe = new FileEntry(r.name, r.size, r.updated_time, r.updated_time);
+ var fe = new FileEntry(r.name, r.size.Value, r.updated_time.Value, r.updated_time.Value);
fe.IsFolder = string.Equals(r.type, "folder", StringComparison.OrdinalIgnoreCase);
files.Add(fe);
}
@@ -293,6 +307,7 @@ namespace Duplicati.Library.Backend
var id = GetFileID(remotename);
var url = string.Format("{0}/{1}?access_token={2}", WLID_SERVER, id, Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
var req = (HttpWebRequest)WebRequest.Create(url);
+ req.UserAgent = USER_AGENT;
req.Method = "DELETE";
var areq = new Utility.AsyncHttpRequest(req);
@@ -354,8 +369,9 @@ namespace Duplicati.Library.Backend
{
var url = string.Format("{0}/me?access_token={1}", WLID_SERVER, Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
var req = (HttpWebRequest)WebRequest.Create(url);
+ req.UserAgent = USER_AGENT;
var areq = new Utility.AsyncHttpRequest(req);
-
+
using(var resp = (HttpWebResponse)areq.GetResponse())
using(var rs = areq.GetResponseStream())
using(var tr = new System.IO.StreamReader(rs))
@@ -367,6 +383,79 @@ namespace Duplicati.Library.Backend
}
}
+ #region IRenameEnabledBackend
+
+ public void Rename(string oldname, string newname)
+ {
+ try
+ {
+ try
+ {
+ var id = GetFileID(oldname);
+ var url = string.Format("{0}/{1}?access_token={2}", WLID_SERVER, id, Library.Utility.Uri.UrlEncode(m_oauth.AccessToken));
+ var req = (HttpWebRequest)WebRequest.Create(url);
+ req.UserAgent = USER_AGENT;
+ req.Method = "PUT";
+
+ var updateData = new WLID_FolderItem() { name = newname };
+ var data = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(updateData));
+ req.ContentLength = data.Length;
+ req.ContentType = "application/json; charset=UTF-8";
+ using (var requestStream = req.GetRequestStream())
+ requestStream.Write(data, 0, data.Length);
+
+ var areq = new Utility.AsyncHttpRequest(req);
+ using (var resp = (HttpWebResponse)areq.GetResponse())
+ {
+ if (resp.StatusCode == System.Net.HttpStatusCode.NotFound)
+ throw new FileMissingException();
+
+ if ((int)resp.StatusCode < 200 || (int)resp.StatusCode > 299)
+ throw new ProtocolViolationException(Strings.OneDrive.UnexpectedError(resp.StatusCode, resp.StatusDescription));
+
+ m_fileidCache[newname] = id;
+ m_fileidCache.Remove(oldname);
+ }
+ }
+ catch
+ {
+ // Since we don't know the state of file IDs, clear the cache
+ m_fileidCache.Clear();
+
+ throw;
+ }
+ }
+ catch (System.Net.WebException wex)
+ {
+ if (wex.Response is System.Net.HttpWebResponse && ((System.Net.HttpWebResponse)wex.Response).StatusCode == System.Net.HttpStatusCode.NotFound)
+ throw new FileMissingException(wex);
+ else
+ throw;
+ }
+ }
+
+ #endregion
+
+ #region IQuotaEnabledBackend Members
+
+ public long TotalQuotaSpace
+ {
+ get
+ {
+ return this.GetQuotaInfo().Quota ?? -1;
+ }
+ }
+
+ public long FreeQuotaSpace
+ {
+ get
+ {
+ return this.GetQuotaInfo().Available ?? -1;
+ }
+ }
+
+ #endregion
+
#region IStreamingBackend Members
public void Put(string remotename, System.IO.Stream stream)
diff --git a/Duplicati/Library/Interface/IBackend.cs b/Duplicati/Library/Interface/IBackend.cs
index df78a28d7..a8b5532b9 100644
--- a/Duplicati/Library/Interface/IBackend.cs
+++ b/Duplicati/Library/Interface/IBackend.cs
@@ -48,7 +48,6 @@ namespace Duplicati.Library.Interface
/// <summary>
/// Returns a list of files found on the remote location
/// </summary>
- /// <param name="url">The url passed</param>
/// <returns>The list of files</returns>
List<IFileEntry> List();
@@ -82,7 +81,7 @@ namespace Duplicati.Library.Interface
/// </summary>
string Description { get; }
- /// <summary>
+ /// <summary>
/// The purpose of this method is to test the connection to the remote backend.
/// If any problem is encountered, this method should throw an exception.
/// If the encountered problem is a missing target &quot;folder&quot;,
diff --git a/Duplicati/Library/Interface/IRenameEnabledBackend.cs b/Duplicati/Library/Interface/IRenameEnabledBackend.cs
index 1185b8c53..550e098e9 100644
--- a/Duplicati/Library/Interface/IRenameEnabledBackend.cs
+++ b/Duplicati/Library/Interface/IRenameEnabledBackend.cs
@@ -24,17 +24,15 @@ using System.Text;
namespace Duplicati.Library.Interface
{
/// <summary>
- /// An interface a backend may implement if it supports streaming operations.
- /// Backends that implement this interface can be throttled and correctly shows
- /// the progressbar when transfering data.
+ /// An interface a backend may implement if it supports rename operations.
/// </summary>
public interface IRenameEnabledBackend : IBackend
{
/// <summary>
- /// Puts the content of the file to the url passed
+ /// Renames the file
/// </summary>
- /// <param name="remotename">The remote filename, relative to the URL</param>
- /// <param name="stream">The stream to read from</param>
+ /// <param name="oldname">The old filename, relative to the root</param>
+ /// <param name="newname">The new filename, relative to the root</param>
void Rename(string oldname, string newname);
}
}
diff --git a/Duplicati/Library/Main/Operation/FilelistProcessor.cs b/Duplicati/Library/Main/Operation/FilelistProcessor.cs
index 0280bafc6..d1a07875a 100644
--- a/Duplicati/Library/Main/Operation/FilelistProcessor.cs
+++ b/Duplicati/Library/Main/Operation/FilelistProcessor.cs
@@ -216,9 +216,9 @@ namespace Duplicati.Library.Main.Operation
where n.FileType == RemoteVolumeType.Files orderby n.Time descending
select n).ToList();
- log.KnownFileCount = remotelist.Count();
+ log.KnownFileCount = remotelist.Count;
log.KnownFileSize = remotelist.Select(x => Math.Max(0, x.File.Size)).Sum();
- log.UnknownFileCount = unknownlist.Count();
+ log.UnknownFileCount = unknownlist.Count;
log.UnknownFileSize = unknownlist.Select(x => Math.Max(0, x.Size)).Sum();
log.BackupListCount = filesets.Count;
log.LastBackupDate = filesets.Count == 0 ? new DateTime(0) : filesets[0].Time.ToLocalTime();
diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs
index 84dd8de5c..b14c5aaa1 100644
--- a/Duplicati/Library/Main/Options.cs
+++ b/Duplicati/Library/Main/Options.cs
@@ -22,6 +22,7 @@ using System.Linq;
using System.Collections.Generic;
using System.Text;
using Duplicati.Library.Interface;
+using Duplicati.Library.Utility;
namespace Duplicati.Library.Main
{
@@ -462,6 +463,8 @@ namespace Duplicati.Library.Main
new CommandLineArgument("quota-size", CommandLineArgument.ArgumentType.Size, Strings.Options.QuotasizeShort, Strings.Options.QuotasizeLong),
+ new CommandLineArgument("default-filters", CommandLineArgument.ArgumentType.String, Strings.Options.DefaultFiltersShort, Strings.Options.DefaultFiltersLong(DefaultFilterSet.Windows.ToString(), DefaultFilterSet.OSX.ToString(), DefaultFilterSet.Linux.ToString(), DefaultFilterSet.All.ToString()), string.Empty, new[] { "default-filter" }),
+
new CommandLineArgument("symlink-policy", CommandLineArgument.ArgumentType.Enumeration, Strings.Options.SymlinkpolicyShort, Strings.Options.SymlinkpolicyLong("store", "ignore", "follow"), Enum.GetName(typeof(SymlinkStrategy), SymlinkStrategy.Store), null, Enum.GetNames(typeof(SymlinkStrategy))),
new CommandLineArgument("hardlink-policy", CommandLineArgument.ArgumentType.Enumeration, Strings.Options.HardlinkpolicyShort, Strings.Options.HardlinkpolicyLong("first", "all", "none"), Enum.GetName(typeof(HardlinkStrategy), HardlinkStrategy.All), null, Enum.GetNames(typeof(HardlinkStrategy))),
new CommandLineArgument("exclude-files-attributes", CommandLineArgument.ArgumentType.String, Strings.Options.ExcludefilesattributesShort, Strings.Options.ExcludefilesattributesLong(Enum.GetNames(typeof(System.IO.FileAttributes)))),
@@ -480,8 +483,8 @@ namespace Duplicati.Library.Main
new CommandLineArgument("skip-metadata", CommandLineArgument.ArgumentType.Boolean, Strings.Options.SkipmetadataShort, Strings.Options.SkipmetadataLong, "false"),
new CommandLineArgument("restore-permissions", CommandLineArgument.ArgumentType.Boolean, Strings.Options.RestorepermissionsShort, Strings.Options.RestorepermissionsLong, "false"),
new CommandLineArgument("skip-restore-verification", CommandLineArgument.ArgumentType.Boolean, Strings.Options.SkiprestoreverificationShort, Strings.Options.SkiprestoreverificationLong, "false"),
- new CommandLineArgument("disable-filepath-cache", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisablefilepathcacheShort, Strings.Options.DisablefilepathcacheLong, "true"),
- new CommandLineArgument("use-block-cache", CommandLineArgument.ArgumentType.Boolean, Strings.Options.UseblockcacheShort, Strings.Options.UseblockcacheLong, "false"),
+ new CommandLineArgument("disable-filepath-cache", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisablefilepathcacheShort, Strings.Options.DisablefilepathcacheLong, "true"),
+ new CommandLineArgument("use-block-cache", CommandLineArgument.ArgumentType.Boolean, Strings.Options.UseblockcacheShort, Strings.Options.UseblockcacheLong, "false"),
new CommandLineArgument("changed-files", CommandLineArgument.ArgumentType.Path, Strings.Options.ChangedfilesShort, Strings.Options.ChangedfilesLong),
new CommandLineArgument("deleted-files", CommandLineArgument.ArgumentType.Path, Strings.Options.DeletedfilesShort, Strings.Options.DeletedfilesLong("changed-files")),
new CommandLineArgument("disable-synthetic-filelist", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisablesyntheticfilelistShort, Strings.Options.DisablesyntehticfilelistLong, "false"),
@@ -1462,7 +1465,7 @@ namespace Duplicati.Library.Main
{
get
{
- return Library.Utility.Utility.ParseBoolOption(m_options, "use-block-cache");
+ return Library.Utility.Utility.ParseBoolOption(m_options, "use-block-cache");
}
}
diff --git a/Duplicati/Library/Main/Strings.cs b/Duplicati/Library/Main/Strings.cs
index 9160b7d84..4c268b7ca 100644
--- a/Duplicati/Library/Main/Strings.cs
+++ b/Duplicati/Library/Main/Strings.cs
@@ -119,6 +119,8 @@ namespace Duplicati.Library.Main.Strings
public static string UploadUnchangedBackupsShort { get { return LC.L(@"Upload empty backup files"); } }
public static string QuotasizeLong { get { return LC.L(@"This value can be used to set a known upper limit on the amount of space a backend has. If the backend reports the size itself, this value is ignored"); } }
public static string QuotasizeShort { get { return LC.L(@"A reported maximum storage"); } }
+ public static string DefaultFiltersLong(string windows, string osx, string linux, string all) { return LC.L(@"Exclude files that match the given filter sets. Which default filter sets should be used. Valid sets are ""{0}"", ""{1}"", ""{2}"", and ""{3}"". If this parameter is set with no value, the set for the current operating system will be used.", windows, osx, linux, all); }
+ public static string DefaultFiltersShort { get { return LC.L(@"Default filter sets"); } }
public static string SymlinkpolicyShort { get { return LC.L(@"Symlink handling"); } }
public static string SymlinkpolicyLong(string store, string ignore, string follow) { return LC.L(@"Use this option to handle symlinks differently. The ""{0}"" option will simply record a symlink with its name and destination, and a restore will recreate the symlink as a link. Use the option ""{1}"" to ignore all symlinks and not store any information about them. Previous versions of Duplicati used the setting ""{2}"", which will cause symlinked files to be included and restore as normal files.", store, ignore, follow); }
public static string HardlinkpolicyShort { get { return LC.L(@"Hardlink handling"); } }
@@ -144,9 +146,9 @@ namespace Duplicati.Library.Main.Strings
public static string FilehashlookupsizeLong { get { return LC.L(@"A fragment of memory is used to reduce database lookups. You should not change this value unless you get warnings in the log."); } }
public static string FilehashlookupsizeShort { get { return LC.L(@"Memory used by the file hash"); } }
public static string DisablefilepathcacheLong { get { return LC.L(@"This option can be used to reduce the memory footprint by not keeping paths and modification timestamps in memory"); } }
- public static string DisablefilepathcacheShort { get { return LC.L(@"Reduce memory footprint by disabling in-memory lookups"); } }
- public static string UseblockcacheShort { get { return LC.L(@"This option can be used to increase speed in exchange for extra memory use."); } }
- public static string UseblockcacheLong { get { return LC.L(@"Store an in-memory block cache"); } }
+ public static string DisablefilepathcacheShort { get { return LC.L(@"Reduce memory footprint by disabling in-memory lookups"); } }
+ public static string UseblockcacheShort { get { return LC.L(@"This option can be used to increase speed in exchange for extra memory use."); } }
+ public static string UseblockcacheLong { get { return LC.L(@"Store an in-memory block cache"); } }
public static string StoremetadataLong { get { return LC.L(@"Stores metadata, such as file timestamps and attributes. This increases the required storage space as well as the processing time."); } }
public static string StoremetadataShort { get { return LC.L(@"Enables storing file metadata"); } }
public static string StoremetadataDeprecated { get { return LC.L(@"This option is no longer used as metadata is now stored by default"); } }