use of org.syncany.operations.down.actions.FileSystemAction in project syncany by syncany.
the class FileSystemActionReconciliatorTest method testFileSystemActionReconDeleteNonExistingFolder.
@Test
public void testFileSystemActionReconDeleteNonExistingFolder() throws Exception {
// Setup
TransferSettings testConnection = TestConfigUtil.createTestLocalConnection();
TestClient clientA = new TestClient("A", testConnection);
Config testConfigA = clientA.getConfig();
// - Create first database version
clientA.createNewFolder("new folder/some subfolder");
clientA.upWithForceChecksum();
// Delete this!
clientA.deleteFile("new folder/some subfolder");
// - Create new version (delete folder)
TestSqlDatabase sqlDatabaseA = new TestSqlDatabase(testConfigA);
PartialFileHistory folderFileHistoryWithLastVersion = sqlDatabaseA.getFileHistoryWithLastVersion("new folder/some subfolder");
FileVersion deletedFolderVersion = folderFileHistoryWithLastVersion.getLastVersion().clone();
deletedFolderVersion.setStatus(FileStatus.DELETED);
deletedFolderVersion.setVersion(deletedFolderVersion.getVersion() + 1);
PartialFileHistory deletedFolderVersionHistory = new PartialFileHistory(folderFileHistoryWithLastVersion.getFileHistoryId());
deletedFolderVersionHistory.addFileVersion(deletedFolderVersion);
DatabaseVersion winnersDatabaseVersion = TestDatabaseUtil.createDatabaseVersion(sqlDatabaseA.getLastDatabaseVersionHeader());
winnersDatabaseVersion.addFileHistory(deletedFolderVersionHistory);
// - Create memory database with this version
MemoryDatabase winnersDatabase = new MemoryDatabase();
winnersDatabase.addDatabaseVersion(winnersDatabaseVersion);
// Run! Finally!
DownOperationResult outDownOperationResult = new DownOperationResult();
FileSystemActionReconciliator fileSystemActionReconciliator = new FileSystemActionReconciliator(testConfigA, outDownOperationResult.getChangeSet());
List<FileSystemAction> fileSystemActions = fileSystemActionReconciliator.determineFileSystemActions(winnersDatabase);
assertNotNull(fileSystemActions);
assertEquals(0, fileSystemActions.size());
// Tear down
clientA.deleteTestData();
}
use of org.syncany.operations.down.actions.FileSystemAction in project syncany by syncany.
the class FileSystemActionComparator method postCompareSort.
/**
* Fixes the case in which a folder has been swapped with a file (case 5a, see above)
*
* New/Renamed file system actions must happen *after* the file was deleted. This method
* moves new/renamed actions below deleted folder actions.
*
* DEL FILE file1.jpg
* NEW FOLDER folder1
* NEW FILE folder1/fileinfolder1.jpg < No Issue, but needs to be checked
* NEW FILE folder2 <<< Issue, because folder2 is deleted below!
* NEW SYMLINK folder1/symlinkinfolder1.jpg < No Issue, but needs to be checked
* REN FILE folder2/fileinfolder2.jpg -> folder1/x2.jpg
* REN SYMLINK folder2/symlinkinfolder2.jpg -> folder1/sym2
* DEL FOLDER folder2
* <<< New position of "NEW FILE folder2"!
*/
public void postCompareSort(List<FileSystemAction> actions) {
List<FileSystemAction> fixedActions = new ArrayList<FileSystemAction>(actions);
int i = 0;
while (i < fixedActions.size()) {
FileSystemAction currentAction = fixedActions.get(i);
if (currentAction instanceof DeleteFileSystemAction && currentAction.getType() == FileType.FOLDER) {
break;
}
//System.out.println("testing "+currentAction);
if ((currentAction instanceof NewFileSystemAction || currentAction instanceof RenameFileSystemAction) && (currentAction.getType() == FileType.FILE || currentAction.getType() == FileType.SYMLINK)) {
int conflictingDeleteActionIndex = getPathConflictingWithDeleteActionIndex(currentAction, fixedActions);
if (conflictingDeleteActionIndex >= 0) {
logger.log(Level.INFO, " --> match, conflict [" + i + "]: " + currentAction);
logger.log(Level.INFO, " with [" + conflictingDeleteActionIndex + "]: " + fixedActions.get(conflictingDeleteActionIndex));
fixedActions.remove(i);
fixedActions.add(conflictingDeleteActionIndex, currentAction);
// fix counter!
i--;
}
}
i++;
}
// Replace
actions.clear();
actions.addAll(fixedActions);
}
use of org.syncany.operations.down.actions.FileSystemAction in project syncany by syncany.
the class FileSystemActionReconciliator method determineActionFileHistoryNotInWinnerBranch.
private void determineActionFileHistoryNotInWinnerBranch(FileVersion localLastVersion, File localLastFile, List<FileSystemAction> fileSystemActions) {
// No local file version in local database
if (localLastVersion == null) {
throw new RuntimeException("This should not happen.");
} else // Local version found in local database
{
FileSystemAction action = new DeleteFileSystemAction(config, localLastVersion, localLastVersion, null);
fileSystemActions.add(action);
logger.log(Level.INFO, " -> (17) Local file exists, but not in winner branch -> File was deleted remotely: local file = " + localLastFile + ", local version = " + localLastVersion + ", winning version = (none)");
logger.log(Level.INFO, " -> " + action);
changeSet.getDeletedFiles().add(localLastVersion.getPath());
}
}
use of org.syncany.operations.down.actions.FileSystemAction in project syncany by syncany.
the class FileSystemActionReconciliator method determineFileSystemActions.
public List<FileSystemAction> determineFileSystemActions(MemoryDatabase winnersDatabase, boolean cleanupOccurred, List<PartialFileHistory> localFileHistoriesWithLastVersion) throws Exception {
this.assembler = new Assembler(config, localDatabase, winnersDatabase);
List<FileSystemAction> fileSystemActions = new ArrayList<FileSystemAction>();
// Load file history cache
logger.log(Level.INFO, "- Loading current file tree...");
Map<FileHistoryId, FileVersion> localFileHistoryIdCache = fillFileHistoryIdCache(localFileHistoriesWithLastVersion);
logger.log(Level.INFO, "- Determine filesystem actions ...");
for (PartialFileHistory winningFileHistory : winnersDatabase.getFileHistories()) {
// Get remote file version and content
FileVersion winningLastVersion = winningFileHistory.getLastVersion();
File winningLastFile = new File(config.getLocalDir(), winningLastVersion.getPath());
// Get local file version and content
FileVersion localLastVersion = localFileHistoryIdCache.get(winningFileHistory.getFileHistoryId());
File localLastFile = (localLastVersion != null) ? new File(config.getLocalDir(), localLastVersion.getPath()) : null;
logger.log(Level.INFO, " + Comparing local version: " + localLastVersion);
logger.log(Level.INFO, " with winning version : " + winningLastVersion);
// No local file version in local database
if (localLastVersion == null) {
determineActionNoLocalLastVersion(winningLastVersion, winningLastFile, winnersDatabase, fileSystemActions);
} else // Local version found in local database
{
FileVersionComparison localFileToVersionComparison = fileVersionComparator.compare(localLastVersion, localLastFile, true);
// Local file on disk as expected
if (localFileToVersionComparison.areEqual()) {
determineActionWithLocalVersionAndLocalFileAsExpected(winningLastVersion, winningLastFile, localLastVersion, localLastFile, winnersDatabase, fileSystemActions);
} else // Local file NOT what was expected
{
determineActionWithLocalVersionAndLocalFileDiffers(winningLastVersion, winningLastFile, localLastVersion, localLastFile, winnersDatabase, fileSystemActions, localFileToVersionComparison);
}
}
}
if (cleanupOccurred) {
logger.log(Level.INFO, "- Determine filesystem actions (for deleted histories in winner's branch)...");
Map<FileHistoryId, FileVersion> winnerFileHistoryIdCache = fillFileHistoryIdCache(winnersDatabase.getFileHistories());
for (PartialFileHistory localFileHistoryWithLastVersion : localFileHistoriesWithLastVersion) {
boolean localFileHistoryInWinnersDatabase = winnerFileHistoryIdCache.get(localFileHistoryWithLastVersion.getFileHistoryId()) != null;
if (!localFileHistoryInWinnersDatabase) {
FileVersion localLastVersion = localFileHistoryWithLastVersion.getLastVersion();
File localLastFile = (localLastVersion != null) ? new File(config.getLocalDir(), localLastVersion.getPath()) : null;
determineActionFileHistoryNotInWinnerBranch(localLastVersion, localLastFile, fileSystemActions);
}
}
}
return fileSystemActions;
}
use of org.syncany.operations.down.actions.FileSystemAction in project syncany by syncany.
the class FileSystemActionReconciliator method determineActionNoLocalLastVersion.
private void determineActionNoLocalLastVersion(FileVersion winningLastVersion, File winningLastFile, MemoryDatabase winnersDatabase, List<FileSystemAction> outFileSystemActions) throws Exception {
FileVersionComparison winningFileToVersionComparison = fileVersionComparator.compare(winningLastVersion, winningLastFile, true);
boolean contentChanged = winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_CHECKSUM) || winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_SIZE);
if (winningFileToVersionComparison.areEqual()) {
logger.log(Level.INFO, " -> (1) Equals: Nothing to do, winning version equals winning file: " + winningLastVersion + " AND " + winningLastFile);
} else if (winningFileToVersionComparison.getFileChanges().contains(FileChange.DELETED)) {
FileSystemAction action = new NewFileSystemAction(config, winnersDatabase, assembler, winningLastVersion);
outFileSystemActions.add(action);
logger.log(Level.INFO, " -> (2) Deleted: Local file does NOT exist, but it should, winning version not known: " + winningLastVersion + " AND " + winningLastFile);
logger.log(Level.INFO, " -> " + action);
changeSet.getNewFiles().add(winningLastVersion.getPath());
} else if (winningFileToVersionComparison.getFileChanges().contains(FileChange.NEW)) {
FileSystemAction action = new DeleteFileSystemAction(config, null, winningLastVersion, winnersDatabase);
outFileSystemActions.add(action);
logger.log(Level.INFO, " -> (3) New: winning version was deleted, but local exists, winning version = " + winningLastVersion + " at " + winningLastFile);
logger.log(Level.INFO, " -> " + action);
changeSet.getDeletedFiles().add(winningLastVersion.getPath());
} else if (winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_LINK_TARGET)) {
FileSystemAction action = new NewSymlinkFileSystemAction(config, winningLastVersion, winnersDatabase);
outFileSystemActions.add(action);
logger.log(Level.INFO, " -> (4) Changed link target: winning file has a different link target: " + winningLastVersion + " AND " + winningLastFile);
logger.log(Level.INFO, " -> " + action);
changeSet.getNewFiles().add(winningLastVersion.getPath());
} else if (!contentChanged && (winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_LAST_MOD_DATE) || winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_ATTRIBUTES))) {
FileSystemAction action = new SetAttributesFileSystemAction(config, winningLastVersion, winnersDatabase);
outFileSystemActions.add(action);
logger.log(Level.INFO, " -> (5) Changed file attributes: winning file has different file attributes: " + winningLastVersion + " AND " + winningLastFile);
logger.log(Level.INFO, " -> " + action);
changeSet.getNewFiles().add(winningLastVersion.getPath());
} else if (winningFileToVersionComparison.getFileChanges().contains(FileChange.CHANGED_PATH)) {
logger.log(Level.INFO, " -> (6) Changed path: winning file has a different path: " + winningLastVersion + " AND " + winningLastFile);
throw new Exception("What happend here?");
} else {
// Content changed
FileSystemAction action = new NewFileSystemAction(config, winnersDatabase, assembler, winningLastVersion);
outFileSystemActions.add(action);
logger.log(Level.INFO, " -> (7) Content changed: Winning file differs from winning version: " + winningLastVersion + " AND " + winningLastFile);
logger.log(Level.INFO, " -> " + action);
changeSet.getNewFiles().add(winningLastVersion.getPath());
}
}
Aggregations