Created separate AssemblyVersion file used by all Pithos projects to hold common version number
<DependentUpon>ProxyAccountView.xaml</DependentUpon>
</Compile>
<Compile Include="Preferences\ProxyAccountViewModel.cs" />
+ <Compile Include="Properties\AssemblyVersion.cs" />
<Compile Include="Proxy.cs" />
<Compile Include="Shell\AboutView.xaml.cs">
<DependentUpon>AboutView.xaml</DependentUpon>
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
+[assembly: AssemblyProduct("Pithos+ Client for Windows")]
[assembly: AssemblyTitle("Pithos+ Client for Windows")]
[assembly: AssemblyDescription("Pithos+ Client for Windows")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GRNET")]
-[assembly: AssemblyProduct("Pithos+ Client for Windows")]
-[assembly: AssemblyCopyright("Copyright © GRNet 2011-2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyInformationalVersion("2012-06-07")]
+
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.7.20703.1")]
-[assembly: AssemblyFileVersionAttribute("0.7.20703.1")]
--- /dev/null
+#region
+/* -----------------------------------------------------------------------
+ * <copyright file="AssemblyInfo.cs" company="GRNet">
+ *
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ * </copyright>
+ * -----------------------------------------------------------------------
+ */
+#endregion
+using System.Reflection;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyCompany("GRNET")]
+[assembly: AssemblyCopyright("Copyright © GRNet 2011-2012")]
+[assembly: AssemblyInformationalVersion("2012-07-03")]
+
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.7.20704.*")]
}
- client.DeleteObject(null, FolderConstants.PithosContainer, fileName);
+ client.DeleteObject(null, FolderConstants.PithosContainer, fileName, false);
var treeHash = Signature.CalculateTreeHashAsync(filePath, accountInfo.BlockSize, accountInfo.BlockHash, 2, new Progress<double>());
var cloudFile = new ObjectInfo {Account = account, Container = "pithos"};
var container = cloudFile.Container;//?? FolderConstants.PithosContainer;
var client = new CloudFilesClient(accountInfo);
- client.DeleteObject(account, container, cloudFile.Name);
+
+ client.DeleteObject(account, container, cloudFile.Name,cloudFile.IsDirectory);
StatusKeeper.ClearFileStatus(fullPath);
StatusNotification.Notify(new CloudNotification{Data=cloudFile});
//Ignore takes into account Selective Sync
if (Ignore(fullPath))
return;
-
+ PollAgent.PostMove(e);
_eventIdleBatch.Post(e);
}
\r
readonly ConcurrentQueue<IEnumerable<string>> _batchQueue=new ConcurrentQueue<IEnumerable<string>>();\r
\r
+ ConcurrentDictionary<string,MovedEventArgs> _moves=new ConcurrentDictionary<string, MovedEventArgs>(); \r
+\r
+ public void PostMove(MovedEventArgs args)\r
+ {\r
+ TaskEx.Run(() => _moves.AddOrUpdate(args.OldFullPath, args,(s,e)=>e)); \r
+ }\r
+\r
/// <summary>\r
/// Remote files are polled periodically. Any changes are processed\r
/// </summary>\r
var accountBatch = batch.Where(path => path.IsAtOrBelow(account.AccountPath));\r
accountBatches[account.AccountKey] = accountBatch;\r
}\r
+ \r
+ var moves=Interlocked.Exchange(ref _moves, new ConcurrentDictionary<string, MovedEventArgs>());\r
\r
var tasks = new List<Task<DateTime?>>();\r
foreach(var accountInfo in _accounts.Values)\r
{\r
IEnumerable<string> accountBatch ;\r
accountBatches.TryGetValue(accountInfo.AccountKey,out accountBatch);\r
- var t=ProcessAccountFiles (accountInfo, accountBatch, since);\r
+ var t=ProcessAccountFiles (accountInfo, accountBatch, moves,since);\r
tasks.Add(t);\r
}\r
\r
\r
\r
\r
- public async Task<DateTime?> ProcessAccountFiles(AccountInfo accountInfo, IEnumerable<string> accountBatch, DateTime? since = null)\r
+ public async Task<DateTime?> ProcessAccountFiles(AccountInfo accountInfo, IEnumerable<string> accountBatch, ConcurrentDictionary<string, MovedEventArgs> moves, DateTime? since = null)\r
{\r
if (accountInfo == null)\r
throw new ArgumentNullException("accountInfo");\r
\r
var token = _currentOperationCancellation.Token;\r
\r
- var tuples = MergeSources(infos, files, states).ToList();\r
+ var tuples = MergeSources(infos, files, states,moves).ToList();\r
\r
//Process only the changes in the batch file, if one exists\r
var stateTuples = accountBatch==null?tuples:tuples.Where(t => accountBatch.Contains(t.FilePath));\r
//Set the Merkle Hash\r
//SetMerkleHash(accountInfo, tuple);\r
\r
- await SyncSingleItem(accountInfo, tuple, agent, token).ConfigureAwait(false);\r
+ await SyncSingleItem(accountInfo, tuple, agent, moves,token).ConfigureAwait(false);\r
\r
}\r
\r
Pause = false;\r
}\r
\r
- private async Task SyncSingleItem(AccountInfo accountInfo, StateTuple tuple, FileAgent agent, CancellationToken token)\r
+ private async Task SyncSingleItem(AccountInfo accountInfo, StateTuple tuple, FileAgent agent, ConcurrentDictionary<string, MovedEventArgs> moves, CancellationToken token)\r
{\r
Log.DebugFormat("Sync [{0}] C:[{1}] L:[{2}] S:[{3}]", tuple.FilePath, tuple.C, tuple.L, tuple.S);\r
\r
\r
StatusKeeper.StoreInfo(targetPath, tuple.ObjectInfo);\r
\r
- AddRootFolderToSelectives(accountInfo, tuple, targetPath);\r
+ AddOwnFolderToSelectives(accountInfo, tuple, targetPath);\r
}\r
\r
/*\r
\r
if (isUnselectedRootFolder)\r
{\r
- ProcessChildren(accountInfo, tuple, agent, token);\r
+ ProcessChildren(accountInfo, tuple, agent, moves,token);\r
}\r
}\r
}\r
var targetPath = MoveForServerMove(accountInfo, tuple);\r
StatusKeeper.StoreInfo(targetPath, tuple.ObjectInfo);\r
\r
- AddRootFolderToSelectives(accountInfo, tuple, targetPath);\r
+ AddOwnFolderToSelectives(accountInfo, tuple, targetPath);\r
}\r
else\r
{\r
}\r
}\r
\r
- private void AddRootFolderToSelectives(AccountInfo accountInfo, StateTuple tuple, string targetPath)\r
+ private void AddOwnFolderToSelectives(AccountInfo accountInfo, StateTuple tuple, string targetPath)\r
{\r
+ //Not for shared folders\r
+ if (tuple.ObjectInfo.IsShared==true)\r
+ return;\r
//Also ensure that any newly created folders are added to the selectives, if the original folder was selected\r
var containerPath = Path.Combine(accountInfo.AccountPath, tuple.ObjectInfo.Container);\r
\r
//If this is a root folder encountered for the first time\r
if (tuple.L == null && Directory.Exists(tuple.FileInfo.FullName) \r
- && (tuple.FileInfo.FullName.IsAtOrDirectlyBelow(containerPath)))\r
+ && (tuple.FileInfo.FullName.IsAtOrBelow(containerPath)))\r
{\r
\r
var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName);\r
var initialPath = Path.Combine(accountInfo.AccountPath, relativePath);\r
\r
- var hasMoved = true;// !initialPath.Equals(targetPath);\r
- if (hasMoved && Selectives.IsSelected(accountInfo, initialPath))\r
+ //var hasMoved = true;// !initialPath.Equals(targetPath);\r
+ //If the new path is under a selected folder, add it to the selectives as well\r
+ if (Selectives.IsSelected(accountInfo, initialPath))\r
{\r
Selectives.AddUri(accountInfo, tuple.ObjectInfo.Uri);\r
Selectives.Save(accountInfo);\r
}\r
}\r
\r
- private void ProcessChildren(AccountInfo accountInfo, StateTuple tuple, FileAgent agent, CancellationToken token)\r
+ private void ProcessChildren(AccountInfo accountInfo, StateTuple tuple, FileAgent agent, ConcurrentDictionary<string, MovedEventArgs> moves,CancellationToken token)\r
{\r
\r
var dirInfo = tuple.FileInfo as DirectoryInfo;\r
select new StateTuple(file);\r
\r
//Process folders first, to ensure folders appear on the sever as soon as possible\r
- folderTuples.ApplyAction(async t =>await SyncSingleItem(accountInfo, t, agent, token).ConfigureAwait(false));\r
+ folderTuples.ApplyAction(async t =>await SyncSingleItem(accountInfo, t, agent, moves, token).ConfigureAwait(false));\r
\r
- fileTuples.ApplyAction(async t => await SyncSingleItem(accountInfo, t, agent, token).ConfigureAwait(false));\r
+ fileTuples.ApplyAction(async t => await SyncSingleItem(accountInfo, t, agent, moves, token).ConfigureAwait(false));\r
}\r
\r
\r
return results;\r
\r
*/\r
- private IEnumerable<StateTuple> MergeSources(\r
- IEnumerable<Tuple<string, ObjectInfo>> infos, \r
- IEnumerable<FileSystemInfo> files, \r
- IEnumerable<FileState> states)\r
+ private IEnumerable<StateTuple> MergeSources(IEnumerable<Tuple<string, ObjectInfo>> infos, IEnumerable<FileSystemInfo> files, IEnumerable<FileState> states, ConcurrentDictionary<string, MovedEventArgs> moves)\r
{\r
var tuplesByPath = files.ToDictionary(f => f.FullName, f => new StateTuple {FileInfo = f}); new Dictionary<string, StateTuple>();\r
\r
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Pithos.Client.WPF\Properties\AssemblyVersion.cs">
+ <Link>AssemblyVersion.cs</Link>
+ </Compile>
<Compile Include="Agents\Agent.cs" />
<Compile Include="Agents\AgentLocator.cs" />
<Compile Include="Agents\AsyncAutoResetEvent.cs" />
[assembly: AssemblyTitle("Pithos.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GRNet")]
[assembly: AssemblyProduct("Pithos.Core")]
-[assembly: AssemblyCopyright("Copyright © GRNet 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
var deleted= !_client.ObjectExists(_account, PithosContainer, "File1.txt");
Assert.That(deleted, Is.True);
- _client.DeleteObject(_account, PithosContainer, "File1.txt");
+ _client.DeleteObject(_account, PithosContainer, "File1.txt", false);
}
[Test]
var targetExists = _client.ObjectExists(_account, PithosContainer, "File2.txt");
Assert.That(targetExists, Is.True);
- _client.DeleteObject(_account,PithosContainer,"File2.txt");
+ _client.DeleteObject(_account,PithosContainer,"File2.txt", false);
var deleted= !_client.ObjectExists(_account, PithosContainer, "File2.txt");
Assert.That(deleted, Is.True);
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Pithos.Client.WPF\Properties\AssemblyVersion.cs">
+ <Link>AssemblyVersion.cs</Link>
+ </Compile>
<Compile Include="AccountSettings.cs" />
<Compile Include="FileInfoExtensions.cs" />
<Compile Include="FolderConstants.cs" />
[assembly: AssemblyTitle("Pithos.Interfaces")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GRNet")]
[assembly: AssemblyProduct("Pithos.Interfaces")]
-[assembly: AssemblyCopyright("Copyright © GRNet 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
var localInfo = new FileInfo("test.txt");
client.PutObject(null, "Pithos","RootFolder/Folder1/test.txt","test.txt");
- client.DeleteObject(null, "pithos", "RootFolder/Folder1");
+ client.DeleteObject(null, "pithos", "RootFolder/Folder1", false);
Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder/Folder1"));
var folderInfo = client.GetObjectInfo(null, "Pithos", "RootFolder/Folder1");
Assert.IsTrue(client.ObjectExists(null, "Shares",info.Name),"File Created");
- client.DeleteObject(null, "Shares/devguide.pdf",info.Name);
+ client.DeleteObject(null, "Shares/devguide.pdf",info.Name, false);
});
Assert.IsTrue(client.ObjectExists(null, "Shares",info.Name),"File Created");
- client.DeleteObject(null, "Shares",info.Name);
+ client.DeleteObject(null, "Shares",info.Name, false);
Assert.IsFalse(client.ObjectExists(null, "Shares", info.Name),"Container Deleted");
- client.DeleteObject(null, "Moo",info.Name);
+ client.DeleteObject(null, "Moo",info.Name, false);
Assert.IsFalse(client.ObjectExists(null, "Moo", info.Name),"Container Deleted");
});
}
}
- public void DeleteObject(string account, string sourceContainer, string objectName)
+ public void DeleteObject(string account, string sourceContainer, string objectName, bool isDirectory)
{
if (String.IsNullOrWhiteSpace(sourceContainer))
throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
Contract.EndContractBlock();
var targetUrl = FolderConstants.TrashContainer + "/" + objectName;
+/*
+ if (isDirectory)
+ targetUrl = targetUrl + "?delimiter=/";
+*/
+
var sourceUrl = String.Format("/{0}/{1}", sourceContainer, objectName);
using (var client = new RestClient(_baseClient))
var expectedCodes = new[] { HttpStatusCode.OK, HttpStatusCode.NoContent, HttpStatusCode.Created};
var result=(expectedCodes.Contains(client.StatusCode));
- DeleteObject(account, cloudFile.Container, fileUrl);
+ DeleteObject(account, cloudFile.Container, fileUrl, cloudFile.IsDirectory);
return result;
}
catch
#region Object operations
Task GetObject(string account, string container, string objectName, string fileName,CancellationToken cancellationToken);
Task PutObject(string account, string container, string objectName, string fileName, string hash = null, string contentType = "application/octet-stream");
- void DeleteObject(string account, string container, string objectName);
+ void DeleteObject(string account, string container, string objectName,bool isDirectory);
//void DeleteObject(string container, string objectName, string account = null);
void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName);
bool ObjectExists(string account, string container, string objectName);
return default(Task);
}
- public void DeleteObject(string account, string container, string objectName)
+ public void DeleteObject(string account, string container, string objectName,bool isDirectory)
{
Contract.Requires(!String.IsNullOrWhiteSpace(Token));
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Pithos.Client.WPF\Properties\AssemblyVersion.cs">
+ <Link>AssemblyVersion.cs</Link>
+ </Compile>
<Compile Include="AccountInfo.cs" />
<Compile Include="BlockHashAlgorithms.cs" />
<Compile Include="CloudFilesClient.cs" />
[assembly: AssemblyTitle("Pithos.Network")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GRNet")]
[assembly: AssemblyProduct("Pithos.Network")]
-[assembly: AssemblyCopyright("Copyright © GRNet 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\Pithos.Client.WPF\Properties\AssemblyVersion.cs">
+ <Link>AssemblyVersion.cs</Link>
+ </Compile>
<Compile Include="FileContext.cs" />
<Compile Include="IoC.cs" />
<Compile Include="LogCategories.cs" />
[assembly: AssemblyTitle("Pithos.ShellExtensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GRNet")]
[assembly: AssemblyProduct("Pithos.ShellExtensions")]
-[assembly: AssemblyCopyright("Copyright © GRNet 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]