+ private async Task SyncFiles(AccountInfo accountInfo,CloudAction action)
+ {
+ if (accountInfo == null)
+ throw new ArgumentNullException("accountInfo");
+ if (action==null)
+ throw new ArgumentNullException("action");
+ if (action.LocalFile==null)
+ throw new ArgumentException("The action's local file is not specified","action");
+ if (!Path.IsPathRooted(action.LocalFile.FullName))
+ throw new ArgumentException("The action's local file path must be absolute","action");
+ if (action.CloudFile== null)
+ throw new ArgumentException("The action's cloud file is not specified", "action");
+ Contract.EndContractBlock();
+
+ var localFile = action.LocalFile;
+ var cloudFile = action.CloudFile;
+ var downloadPath=action.LocalFile.GetProperCapitalization();
+
+ var cloudHash = cloudFile.Hash.ToLower();
+ var localHash = action.LocalHash.Value.ToLower();
+ var topHash = action.TopHash.Value.ToLower();
+
+ //Not enough to compare only the local hashes, also have to compare the tophashes
+
+ //If any of the hashes match, we are done
+ if ((cloudHash == localHash || cloudHash == topHash))
+ {
+ Log.InfoFormat("Skipping {0}, hashes match",downloadPath);
+ return;
+ }
+
+ //The hashes DON'T match. We need to sync
+ var lastLocalTime = localFile.LastWriteTime;
+ var lastUpTime = cloudFile.Last_Modified;
+
+ //If the local file is newer upload it
+ if (lastUpTime <= lastLocalTime)
+ {
+ //It probably means it was changed while the app was down
+ UploadCloudFile(action);
+ }
+ else
+ {
+ //It the cloud file has a later date, it was modified by another user or computer.
+ //We need to check the local file's status
+ var status = StatusKeeper.GetFileStatus(downloadPath);
+ switch (status)
+ {
+ case FileStatus.Unchanged:
+ //If the local file's status is Unchanged, we can go on and download the newer cloud file
+ await DownloadCloudFile(accountInfo,cloudFile,downloadPath);
+ break;
+ case FileStatus.Modified:
+ //If the local file is Modified, we may have a conflict. In this case we should mark the file as Conflict
+ //We can't ensure that a file modified online since the last time will appear as Modified, unless we
+ //index all files before we start listening.
+ case FileStatus.Created:
+ //If the local file is Created, it means that the local and cloud files aren't related,
+ // yet they have the same name.
+
+ //In both cases we must mark the file as in conflict
+ ReportConflict(downloadPath);
+ break;
+ default:
+ //Other cases should never occur. Mark them as Conflict as well but log a warning
+ ReportConflict(downloadPath);
+ Log.WarnFormat("Unexcepted status {0} for file {1}->{2}", status,
+ downloadPath, action.CloudFile.Name);
+ break;
+ }
+ }
+ }
+
+ private void ReportConflict(string downloadPath)
+ {
+ if (String.IsNullOrWhiteSpace(downloadPath))
+ throw new ArgumentNullException("downloadPath");
+ Contract.EndContractBlock();
+
+ StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
+ var message = String.Format("Conflict detected for file {0}", downloadPath);
+ Log.Warn(message);
+ StatusNotification.NotifyChange(message, TraceLevel.Warning);
+ }