/* low level */ private async Task <DriveItem> TransferDriveItem(IDriveProxy sourceDrive, IDriveProxy targetDrive, DriveItem driveItem) { (var itemName1, var itemName2) = this.GetItemNames(driveItem); var isLocal = sourceDrive == _localDrive; // item exists on target drive if (_syncMode == SyncMode.TwoWay && await targetDrive.ExistsAsync(driveItem)) { // item is unchanged on target drive // actions: do nothing if (await targetDrive.GetLastWriteTimeUtcAsync(driveItem) == driveItem.LastModified()) { _logger.LogDebug($"{itemName1} already exists and is unchanged on target drive '{targetDrive.Name}'. Action(s): do nothing."); } // item was modified on target drive else { if (!isLocal) { _logger.LogDebug($"{itemName1} already exists and was modified on target drive '{targetDrive.Name}'. Action(s): handle conflict."); await this.EnsureLocalConflict(driveItem); } } } // item does not exist on target drive // actions: transfer item else { _logger.LogInformation($"{itemName1} is not available on target drive '{targetDrive.Name}'. Action(s): transfer {itemName2}."); return(await this.InternalTransferDriveItem(sourceDrive, targetDrive, driveItem)); } return(driveItem); }
private async Task <bool> CheckConflict(Conflict conflict) { var remoteItem = _context.RemoteStates.FirstOrDefault(current => current.GetItemPath() == conflict.OriginalFilePath); var originalDriveItem = conflict.OriginalFilePath.ToDriveItem(DriveItemType.File); // original file exists locally if (await _localDrive.ExistsAsync(originalDriveItem)) { _logger.LogDebug($"Original file exists locally."); var conflictDriveItem = conflict.ConflictFilePath.ToDriveItem(DriveItemType.File); // conflict file exists locally // actions: do nothing - user must delete or rename conflict file manually if (await _localDrive.ExistsAsync(conflictDriveItem)) { _logger.LogDebug($"Conflict file exists locally. Action(s): do nothing."); } // conflict file does not exist locally, i.e. conflict is solved else { _logger.LogDebug($"Conflict file does not exist locally."); // remote file is tracked in database if (remoteItem != null) { _logger.LogDebug($"Remote file is tracked in database."); // hashes are equal // actions: do nothing if (await _localDrive.GetHashAsync(originalDriveItem) == remoteItem.QuickXorHash) { _logger.LogDebug($"File is unchanged. Action(s): do nothing."); } // actions: upload file and replace remote version else { _logger.LogInformation($"File was modified. Action(s): upload and replace file."); originalDriveItem = await _localDrive.ToFullDriveItem(originalDriveItem); var driveItem = await _remoteDrive.CreateOrUpdateAsync(originalDriveItem); _context.RemoteStates.Add(driveItem.ToRemoteState()); } } // remote file is not tracked in database (e.g. upload failed previously) // actions: upload file else { _logger.LogInformation($"Remote file is not tracked in database. Action(s): upload file."); originalDriveItem = await _localDrive.ToFullDriveItem(originalDriveItem); var driveItem = await _remoteDrive.CreateOrUpdateAsync(originalDriveItem); _context.RemoteStates.Add(driveItem.ToRemoteState()); } return(true); } } // original file does not exist locally // actions: do nothing - user must delete or rename conflict file manually else { _logger.LogDebug($"Original file does not exist locally. Action(s): do nothing."); } return(false); }
private async Task <(DriveItem UpdateDriveItem, WatcherChangeTypes ChangeType)> SyncDriveItem( IDriveProxy sourceDrive, IDriveProxy targetDrive, DriveItem oldDriveItem, DriveItem newDriveItem) { DriveItem updatedDriveItem; (var itemName1, var itemName2) = this.GetItemNames(newDriveItem); var changeType = newDriveItem.GetChangeType(oldDriveItem); switch (changeType) { case WatcherChangeTypes.Changed: case WatcherChangeTypes.Created: // Item was created or modified on source drive // actions: create or modify on target drive _logger.LogInformation($"{itemName1} was created or modified on drive '{sourceDrive.Name}'. Action(s): Create or modify {itemName2} on drive '{targetDrive.Name}'."); updatedDriveItem = await this.TransferDriveItem(sourceDrive, targetDrive, newDriveItem); break; case WatcherChangeTypes.Deleted: // item was deleted on source drive // actions: delete item on target drive _logger.LogInformation($"{itemName1} was deleted on drive '{sourceDrive.Name}'. Action(s): Delete {itemName2} on drive '{targetDrive.Name}'."); if (await targetDrive.ExistsAsync(newDriveItem)) { updatedDriveItem = await targetDrive.DeleteAsync(newDriveItem); } else { _logger.LogWarning($"Cannot delete {itemName2} because it does not exist on drive '{targetDrive.Name}'."); throw new InvalidOperationException($"Cannot delete {itemName2} because it does not exist on drive '{targetDrive.Name}'."); } break; case WatcherChangeTypes.Renamed: // item was renamed / moved on source drive // actions: rename / move item on target drive _logger.LogInformation($"{itemName1} was renamed / moved on drive '{sourceDrive.Name}'. Action(s): Rename / move {itemName2} on drive '{targetDrive.Name}'."); if (await targetDrive.ExistsAsync(newDriveItem)) { _logger.LogWarning($"Cannot move {itemName2} because the target {itemName2} already exists on drive '{targetDrive.Name}'."); throw new InvalidOperationException($"Cannot move {itemName2} because the target {itemName2} already exists on drive '{targetDrive.Name}'."); } else { updatedDriveItem = await targetDrive.MoveAsync(oldDriveItem, newDriveItem); } break; default: updatedDriveItem = newDriveItem; break; } return(updatedDriveItem, changeType); }