//Don't use the tuple info, it may have been deleted\r
var localInfo = FileInfoExtensions.FromPath(localFilePath);\r
\r
+\r
// Local file unchanged? If both C and L are null, make sure it's because \r
//both the file is missing and the state checksum is not missing\r
if (tuple.C == tuple.L && (localInfo.Exists || tuple.FileState==null))\r
if (tuple.S == tuple.L)\r
{\r
// No server changes\r
- ;\r
+ //Has the file been renamed on the server?\r
+ MoveForServerMove(accountInfo, tuple);\r
}\r
else\r
{\r
{\r
//Server file exists\r
//downloadServerObject() // Result: L = S\r
- StatusKeeper.SetFileState(localFilePath, FileStatus.Modified,\r
+ //If the file has moved on the server, move it locally before downloading\r
+ var targetPath=MoveForServerMove(accountInfo,tuple);\r
+\r
+ StatusKeeper.SetFileState(targetPath, FileStatus.Modified,\r
FileOverlayStatus.Modified, "");\r
NetworkAgent.Downloader.DownloadCloudFile(accountInfo,\r
tuple.ObjectInfo,\r
- localFilePath, token).Wait(token);\r
+ targetPath, token).Wait(token);\r
//updateRecord( L = S )\r
- StatusKeeper.UpdateFileChecksum(localFilePath, tuple.ObjectInfo.ETag,\r
+ StatusKeeper.UpdateFileChecksum(targetPath, tuple.ObjectInfo.ETag,\r
tuple.ObjectInfo.X_Object_Hash);\r
\r
- StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged,\r
+ StatusKeeper.StoreInfo(targetPath, tuple.ObjectInfo);\r
+\r
+/*\r
+ StatusKeeper.SetFileState(targetPath, FileStatus.Unchanged,\r
FileOverlayStatus.Normal, "");\r
+*/\r
}\r
}\r
}\r
"Poll", isUnselected);\r
NetworkAgent.Uploader.UploadCloudFile(action, token).Wait(token);\r
\r
-\r
//updateRecord( S = C )\r
- StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged,\r
- FileOverlayStatus.Normal, "");\r
+ //State updated by the uploader\r
+ \r
if (isUnselected)\r
{\r
ProcessChildren(accountInfo, tuple, agent, token);\r
}\r
}\r
\r
+ private string MoveForServerMove(AccountInfo accountInfo, StateTuple tuple)\r
+ {\r
+ var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName);\r
+ var serverPath = Path.Combine(accountInfo.AccountPath, relativePath);\r
+\r
+ if (tuple.FilePath == serverPath) return serverPath;\r
+\r
+ if (tuple.FileInfo.Exists)\r
+ { \r
+ var fi = tuple.FileInfo as FileInfo;\r
+ if (fi != null)\r
+ fi.MoveTo(serverPath);\r
+ var di = tuple.FileInfo as DirectoryInfo;\r
+ if (di != null)\r
+ di.MoveTo(serverPath);\r
+ StatusKeeper.StoreInfo(serverPath, tuple.ObjectInfo);\r
+ }\r
+ else\r
+ {\r
+ Debug.Assert(false, "File does not exist");\r
+ }\r
+ return serverPath;\r
+ }\r
+\r
private void DeleteCloudFile(AccountInfo accountInfo, StateTuple tuple)\r
{\r
StatusKeeper.SetFileState(tuple.FilePath, FileStatus.Deleted,\r
IEnumerable<Tuple<FileSystemInfo, string>> files, \r
IEnumerable<FileState> states)\r
{\r
- var dct = new Dictionary<string, StateTuple>();\r
+ var tuplesByPath = new Dictionary<string, StateTuple>();\r
foreach (var file in files)\r
{\r
var fsInfo = file.Item1;\r
var fileHash = fsInfo is DirectoryInfo? MERKLE_EMPTY:file.Item2;\r
\r
- dct[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};\r
+ tuplesByPath[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};\r
}\r
foreach (var state in states)\r
{\r
StateTuple hashTuple;\r
- if (dct.TryGetValue(state.FilePath, out hashTuple))\r
+ if (tuplesByPath.TryGetValue(state.FilePath, out hashTuple))\r
{\r
hashTuple.FileState = state;\r
}\r
else\r
{\r
var fsInfo = FileInfoExtensions.FromPath(state.FilePath);\r
- dct[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};\r
+ tuplesByPath[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};\r
}\r
}\r
+\r
+ var tuplesByID = tuplesByPath.Values\r
+ .Where(tuple => tuple.FileState != null && tuple.FileState.ObjectID!=null)\r
+ .ToDictionary(tuple=>tuple.FileState.ObjectID,tuple=>tuple);//new Dictionary<Guid, StateTuple>();\r
+\r
foreach (var info in infos)\r
{\r
StateTuple hashTuple;\r
var filePath = info.Item1;\r
var objectInfo = info.Item2;\r
- if (dct.TryGetValue(filePath, out hashTuple))\r
+ var objectID = objectInfo.UUID;\r
+\r
+ if (tuplesByID.TryGetValue(objectID, out hashTuple))\r
+ {\r
+ hashTuple.ObjectInfo = objectInfo; \r
+ }\r
+ else if (tuplesByPath.TryGetValue(filePath, out hashTuple))\r
{\r
hashTuple.ObjectInfo = objectInfo;\r
}\r
else\r
{\r
var fsInfo = FileInfoExtensions.FromPath(filePath);\r
- dct[filePath] = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo};\r
+ var tuple = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo};\r
+ tuplesByPath[filePath] = tuple;\r
+ tuplesByID[objectInfo.UUID] = tuple;\r
}\r
}\r
- return dct.Values;\r
+ return tuplesByPath.Values;\r
}\r
\r
/// <summary>\r
using (var connection = GetConnection())
using (var command = new SQLiteCommand(connection))
{
- if (StateExists(path, connection))
+ //If the ID exists, update the status
+ if (StateExistsByID(objectInfo.UUID,connection))
command.CommandText =
- "update FileState set FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE ";
+ "update FileState set FilePath=:path,FileStatus= :fileStatus, Checksum=:checksum, ShortHash=:shortHash,Version=:version,VersionTimeStamp=:versionTimeStamp where ObjectID = :objectID ";
+ else if (StateExists(path, connection))
+ //If the ID doesn't exist, try to update using the path, and store the ID as well.
+ command.CommandText =
+ "update FileState set FileStatus= :fileStatus, ObjectID=:objectID, Checksum=:checksum, ShortHash=:shortHash,Version=:version,VersionTimeStamp=:versionTimeStamp where FilePath = :path COLLATE NOCASE ";
else
{
command.CommandText =
}
+ private bool StateExistsByID(string objectId,SQLiteConnection connection)
+ {
+ using (var command = new SQLiteCommand("Select count(*) from FileState where ObjectId=:id", connection))
+ {
+ command.Parameters.AddWithValue("id", objectId);
+ var result = command.ExecuteScalar();
+ return ((long)result >= 1);
+ }
+
+ }
+
public void SetFileStatus(string path, FileStatus status)
{
if (String.IsNullOrWhiteSpace(path))