public override void Solve(
IFileSystemInfo localFile,
IObjectId remoteId,
ContentChangeType localContent = ContentChangeType.NONE,
ContentChangeType remoteContent = ContentChangeType.NONE)
{
if (localFile is IDirectoryInfo) {
if (!(remoteId is IFolder)) {
throw new ArgumentException("remoteId has to be a prefetched Folder");
}
var remoteFolder = remoteId as IFolder;
IDirectoryInfo localFolder = localFile as IDirectoryInfo;
localFolder.Create();
Guid uuid = Guid.Empty;
if (localFolder.IsExtendedAttributeAvailable()) {
uuid = Guid.NewGuid();
try {
localFolder.Uuid = uuid;
} catch (RestoreModificationDateException) {
}
}
if (remoteFolder.LastModificationDate != null) {
try {
localFolder.LastWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
} catch (IOException e) {
Logger.Info("Directory modification date could not be synced", e);
}
}
var mappedObject = new MappedObject(remoteFolder);
mappedObject.Guid = uuid;
mappedObject.LastRemoteWriteTimeUtc = remoteFolder.LastModificationDate;
mappedObject.LastLocalWriteTimeUtc = localFolder.LastWriteTimeUtc;
mappedObject.Ignored = remoteFolder.AreAllChildrenIgnored();
this.Storage.SaveMappedObject(mappedObject);
OperationsLogger.Info(string.Format("New local folder {0} created and mapped to remote folder {1}", localFolder.FullName, remoteId.Id));
} else if (localFile is IFileInfo) {
if (!(remoteId is IDocument)) {
throw new ArgumentException("remoteId has to be a prefetched Document");
}
Guid guid = Guid.NewGuid();
byte[] localFileHash = null;
DateTime? lastLocalFileModificationDate = null;
var file = localFile as IFileInfo;
if (file.Exists) {
Guid? uuid = file.Uuid;
if (uuid != null) {
if (this.Storage.GetObjectByGuid((Guid)uuid) != null) {
throw new ArgumentException("This file has already been synced => force crawl sync");
}
}
lastLocalFileModificationDate = file.LastWriteTimeUtc;
if (this.MergeExistingFileWithRemoteFile(file, remoteId as IDocument, guid, out localFileHash)) {
return;
}
Logger.Debug(string.Format("This file {0} conflicts with remote file => conflict file will could be produced after download", file.FullName));
}
var cacheFile = this.fsFactory.CreateDownloadCacheFileInfo(guid);
IDocument remoteDoc = remoteId as IDocument;
var transmission = this.manager.CreateTransmission(TransmissionType.DOWNLOAD_NEW_FILE, localFile.FullName, cacheFile.FullName);
byte[] hash = DownloadCacheFile(cacheFile, remoteDoc, transmission, this.fsFactory);
try {
cacheFile.Uuid = guid;
} catch(RestoreModificationDateException e) {
Logger.Debug("Could not retore the last modification date of " + cacheFile.FullName, e);
}
try {
cacheFile.MoveTo(file.FullName);
} catch (IOException e) {
file.Refresh();
if (file.Exists) {
if (localFileHash == null ||
lastLocalFileModificationDate == null ||
!lastLocalFileModificationDate.Equals(file.LastWriteTimeUtc)) {
lastLocalFileModificationDate = file.LastWriteTimeUtc;
using (var f = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
localFileHash = SHA1Managed.Create().ComputeHash(f);
}
}
if (localFileHash.SequenceEqual(hash)) {
file.Uuid = guid;
try {
cacheFile.Delete();
} catch(IOException) {
}
} else {
IFileInfo conflictFile = this.fsFactory.CreateConflictFileInfo(file);
try {
IFileInfo targetFile = cacheFile.Replace(file, conflictFile, true);
try {
targetFile.Uuid = guid;
} catch (RestoreModificationDateException restoreException) {
Logger.Debug("Could not retore the last modification date of " + targetFile.FullName, restoreException);
}
} catch (Exception ex) {
transmission.FailedException = ex;
throw;
}
try {
conflictFile.Uuid = null;
} catch(RestoreModificationDateException restoreException) {
Logger.Debug("Could not retore the last modification date of " + conflictFile.FullName, restoreException);
}
}
} else {
transmission.FailedException = e;
throw;
}
}
file.Refresh();
if (remoteDoc.LastModificationDate != null) {
try {
file.LastWriteTimeUtc = (DateTime)remoteDoc.LastModificationDate;
} catch(IOException e) {
Logger.Debug("Cannot set last modification date", e);
}
}
MappedObject mappedObject = new MappedObject(
file.Name,
remoteDoc.Id,
MappedObjectType.File,
remoteDoc.Parents[0].Id,
remoteDoc.ChangeToken,
remoteDoc.ContentStreamLength ?? 0)
{
Guid = guid,
LastLocalWriteTimeUtc = file.LastWriteTimeUtc,
LastRemoteWriteTimeUtc = remoteDoc.LastModificationDate,
LastChecksum = hash,
ChecksumAlgorithmName = "SHA-1"
};
this.Storage.SaveMappedObject(mappedObject);
OperationsLogger.Info(string.Format("New local file {0} created and mapped to remote file {1}", file.FullName, remoteId.Id));
transmission.Status = TransmissionStatus.FINISHED;
}
}