Fix bug in sync daemon when deleting locally objects from different containers/accoun...
[pithos-macos] / pithos-macos / PithosSyncDaemon.m
index 26a4a2c..442bf7e 100644 (file)
@@ -96,7 +96,7 @@
             resetLocalState:(BOOL)resetLocalState {
     if ((self = [super init])) {
         directoryPath = [aDirectoryPath copy];
-        pithosAccount = [aPithosAccount retain];
+        pithosAccount = aPithosAccount;
         self.accountsDictionary = anAccountsDictionary;
         skipHidden = aSkipHidden;
         self.pithos = pithosAccount.pithos;        
                                 [PithosUtilities removeContentsAtPath:[self.tempDownloadsDirPath stringByAppendingPathComponent:containerName]];
                             }
                         } else {
-                            [PithosUtilities removeContentsAtPath:[[self.tempDownloadsDirPath stringByAppendingPathComponent:@"shared to me"] 
+                            [PithosUtilities removeContentsAtPath:[[self.tempDownloadsDirPath stringByAppendingPathComponent:@"shared with me"]
                                                                    stringByAppendingPathComponent:accountName]];
                         }
                     }
                             if ([accountName isEqualToString:@""])
                                 [PithosUtilities removeContentsAtPath:[self.tempDownloadsDirPath stringByAppendingPathComponent:containerName]];
                             else
-                                [PithosUtilities removeContentsAtPath:[[[self.tempDownloadsDirPath stringByAppendingPathComponent:@"shared to me"] 
+                                [PithosUtilities removeContentsAtPath:[[[self.tempDownloadsDirPath stringByAppendingPathComponent:@"shared with me"]
                                                                         stringByAppendingPathComponent:accountName] 
                                                                        stringByAppendingPathComponent:containerName]];
                             [accountStoredLocalObjectStates removeObjectForKey:containerName];
 - (void)dealloc {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     [self resetDaemon];
-    [callbackQueue release];
-    [networkQueue release];
-    [tempTrashDirPath release];
-    [tempDownloadsDirPath release];
-    [pithosStateFilePath release];
-    [currentLocalObjectStates release];
-    [storedLocalObjectStates release];
-    [previousRemoteObjects release];
-    [remoteObjects release];
-    [objects release];
-    [lastCompletedSync release];
-    [accountsPithosContainers release];
-    [accountsNames release];
-    [pithos release];
-    [accountsDictionary release];
-    [pithosAccount release];
-    [directoryPath release];
-    [super dealloc];
 }
 
 #pragma mark -
 
 - (NSString *)pithosStateFilePath {
     if (!pithosStateFilePath) {
-        pithosStateFilePath = [[[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
+        pithosStateFilePath = [[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
                                  stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]] 
                                 stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-PithosLocalObjectStates.archive", 
-                                                                pithosAccount.uniqueName]] retain];
+                                                                pithosAccount.uniqueName]];
         NSString *pithosStateFileDirPath = [pithosStateFilePath stringByDeletingLastPathComponent];
         NSFileManager *fileManager = [NSFileManager defaultManager];
         BOOL isDirectory;
         //  pithosStateFilePath = nil;
         // XXX create a dir using mktmps?
     }
-    return [[pithosStateFilePath copy] autorelease];
+    return [pithosStateFilePath copy];
 }
 
 - (NSString *)tempDownloadsDirPath {
     if (!tempDownloadsDirPath) {
-        tempDownloadsDirPath = [[[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
+        tempDownloadsDirPath = [[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
                                   stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]] 
                                  stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-TempDownloads", 
-                                                                 pithosAccount.uniqueName]] retain];
+                                                                 pithosAccount.uniqueName]];
         NSFileManager *fileManager = [NSFileManager defaultManager];
         BOOL isDirectory;
         BOOL fileExists = [fileManager fileExistsAtPath:tempDownloadsDirPath isDirectory:&isDirectory];
 
 - (NSString *)tempTrashDirPath {
     if (!tempTrashDirPath) {
-        tempTrashDirPath = [[[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
+        tempTrashDirPath = [[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
                                   stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]] 
                                  stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-TempTrash", 
-                                                                 pithosAccount.uniqueName]] retain];
+                                                                 pithosAccount.uniqueName]];
         NSFileManager *fileManager = [NSFileManager defaultManager];
         BOOL isDirectory;
         BOOL fileExists = [fileManager fileExistsAtPath:tempTrashDirPath isDirectory:&isDirectory];
     if (aDirectoryPath && ![aDirectoryPath isEqualToString:directoryPath]) {
         [self resetDaemon];
         [self resetLocalStateWithAll:YES];
-        [directoryPath release];
         directoryPath = [aDirectoryPath copy];
     }
 }
         if (reset)
             [self resetDaemon];
         
-        [accountsDictionary release];
         accountsDictionary = [anAccountsDictionary copy];
         
         accountsCount = [accountsDictionary count];
 
 - (void)setPithos:(ASIPithos *)aPithos {
     if (!pithos) {
-        pithos = [[ASIPithos pithos] retain];
-        pithos.authUser = [[aPithos.authUser copy] autorelease];
-        pithos.authToken = [[aPithos.authToken copy] autorelease];
-        pithos.storageURLPrefix = [[aPithos.storageURLPrefix copy] autorelease];
-        pithos.authURL = [[aPithos.authURL copy] autorelease];
-        pithos.publicURLPrefix = [[aPithos.publicURLPrefix copy] autorelease];
+        pithos = [ASIPithos pithos];
+        pithos.authUser = [aPithos.authUser copy];
+        pithos.authToken = [aPithos.authToken copy];
+        pithos.storageURLPrefix = [aPithos.storageURLPrefix copy];
+        pithos.authURL = [aPithos.authURL copy];
+        pithos.publicURLPrefix = [aPithos.publicURLPrefix copy];
+        pithos.userCatalogURL = [aPithos.userCatalogURL copy];
     }
     if (aPithos && 
         (![aPithos.authUser isEqualToString:pithos.authUser] || 
         if (![aPithos.authUser isEqualToString:pithos.authUser] || 
             ![aPithos.storageURLPrefix isEqualToString:pithos.storageURLPrefix])
             [self resetLocalStateWithAll:YES];
-        pithos.authUser = [[aPithos.authUser copy] autorelease];
-        pithos.authToken = [[aPithos.authToken copy] autorelease];
-        pithos.storageURLPrefix = [[aPithos.storageURLPrefix copy] autorelease];
-        pithos.authURL = [[aPithos.authURL copy] autorelease];
-        pithos.publicURLPrefix = [[aPithos.publicURLPrefix copy] autorelease];
-    }        
+        pithos.authUser = [aPithos.authUser copy];
+        pithos.authToken = [aPithos.authToken copy];
+        pithos.storageURLPrefix = [aPithos.storageURLPrefix copy];
+        pithos.authURL = [aPithos.authURL copy];
+        pithos.publicURLPrefix = [aPithos.publicURLPrefix copy];
+        pithos.userCatalogURL = [aPithos.userCatalogURL copy];
+    }
 }
 
 #pragma mark -
     if ([accountName isEqualToString:@""])
         return [directoryPath stringByAppendingPathComponent:containerName];
     else
-        return [[[directoryPath stringByAppendingPathComponent:@"shared to me"] 
+        return [[[directoryPath stringByAppendingPathComponent:@"shared with me"]
                  stringByAppendingPathComponent:accountName] 
                 stringByAppendingPathComponent:containerName];
 }
     if ([accountName isEqualToString:@""])
         return containerName;
     else
-        return [[@"shared to me" stringByAppendingPathComponent:accountName] stringByAppendingPathComponent:containerName];
+        return [[@"shared with me" stringByAppendingPathComponent:accountName] stringByAppendingPathComponent:containerName];
 }
 
 #pragma mark -
         BOOL isDirectory;
         BOOL fileExists = [fileManager fileExistsAtPath:filePath isDirectory:&isDirectory];
         NSError *error = nil;
-        NSString *containerDirectoryPath = [self dirPathForAccount:accountName container:pithosContainer.name];
-        NSString *newFilePath = [filePath stringByReplacingOccurrencesOfString:containerDirectoryPath withString:self.tempTrashDirPath];
+        NSString *newFilePath = [filePath stringByReplacingOccurrencesOfString:directoryPath withString:self.tempTrashDirPath];
         NSString *newDirPath = [newFilePath stringByDeletingLastPathComponent];
         if (fileExists && isDirectory) {
             NSArray *subPaths = [fileManager subpathsOfDirectoryAtPath:filePath error:&error];
             }
             for (NSString *subPath in subPaths) {
                 NSString *subFilePath = [filePath stringByAppendingPathComponent:subPath];
-                NSString *newSubFilePath = [subFilePath stringByReplacingOccurrencesOfString:containerDirectoryPath 
+                NSString *newSubFilePath = [subFilePath stringByReplacingOccurrencesOfString:directoryPath
                                                                                   withString:self.tempTrashDirPath];
                 currentState = [currentLocalObjectStates objectForKey:subFilePath];
                 if (currentState) {
         if (!object || !object.objectHash) {
             // Delete local object
             if (![accountName isEqualToString:@""])
-                // If "shared to me" skip
+                // If "shared with me" skip
                 return;
             if (remoteObjectExists) {
                 // Remote object created in the meantime, just mark the sync cycle as incomplete, but do delete the local object
                     }
                 }
                 if (![object.allowedTo isEqualToString:@"write"]) {
-                    // If read-only "shared to me" skip
+                    // If read-only "shared with me" skip
                     [self syncOperationFinishedWithSuccess:YES];
                     return;
                 }
         } else if (![currentState exists]) {
             // Delete remote object
             if (![accountName isEqualToString:@""]) {
-                // If "shared to me" skip
+                // If "shared with me" skip
                 [self syncOperationFinishedWithSuccess:YES];
                 return;
             }
                     }
                 }
                 if (![object.allowedTo isEqualToString:@"write"]) {
-                    // If read-only "shared to me" skip
+                    // If read-only "shared with me" skip
                     [self syncOperationFinishedWithSuccess:YES];
                     return;
                 }
 
 - (void)performRequestFinishedDelegateInBackground:(ASIPithosRequest *)request {
     // Add an operation to the callbackQueue with a completionBlock for the case of cancellation
-    NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self 
+    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                                                                              selector:NSSelectorFromString([request.userInfo objectForKey:@"didFinishSelector"]) 
-                                                                               object:request] autorelease];
+                                                                               object:request];
     operation.completionBlock = ^{
         @autoreleasepool {
             if ([[request.userInfo objectForKey:@"operation"] isCancelled]) {
                    withObject:request];
     } else {
         // Add an operation to the callbackQueue with a completionBlock for the case of cancellation
-        NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self 
+        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                                                                                  selector:NSSelectorFromString([request.userInfo objectForKey:@"didFailSelector"]) 
-                                                                                   object:request] autorelease];
+                                                                                   object:request];
         operation.completionBlock = ^{
             @autoreleasepool {
                 if ([[request.userInfo objectForKey:@"operation"] isCancelled]) {
                         [containerRemoteObjects setObject:object forKey:object.name];
                     }
                     [[remoteObjects objectForKey:accountName] setObject:containerRemoteObjects forKey:pithosContainer.name];
-                    [objects release];
                     objects = nil;
                 } else {
                     // Do an additional request to fetch more objects
                     NSMutableDictionary *containerStoredLocalObjectStates = [[storedLocalObjectStates objectForKey:accountName] 
                                                                              objectForKey:pithosContainer.name];
                     NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:containerDirectoryPath];
-                    for (NSString *objectName in dirEnumerator) {
+                    for (__strong NSString *objectName in dirEnumerator) {
                         objectName = [objectName precomposedStringWithCanonicalMapping];
                         if (operation.isCancelled) {
                             operation.completionBlock = nil;
                                 }
                                 __block NSInteger choice;
                                 dispatch_sync(dispatch_get_main_queue(), ^{
-                                    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+                                    NSAlert *alert = [[NSAlert alloc] init];
                                     [alert setMessageText:@"Conflict"];
                                     [alert setInformativeText:informativeText];
                                     [alert addButtonWithTitle:firstButtonText];
     @autoreleasepool {
         NSOperation *operation = [containerRequest.userInfo objectForKey:@"operation"];
         if (operation.isCancelled) {
-            [objects release];
             objects = nil;
             return;        
         }
                 [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"] 
                                   withMessage:[containerRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
             });
-            [objects release];
             objects = nil;
             [self syncOperationFinishedWithSuccess:NO];
             return;
         // If the server listing fails, the sync should start over, so just retrying is enough
         NSUInteger retries = [[containerRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
         if (retries > 0) {
-            ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[[PithosUtilities copyRequest:containerRequest] autorelease];
+            ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[PithosUtilities copyRequest:containerRequest];
             [(NSMutableDictionary *)(newContainerRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
             [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
         } else {
                 [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"] 
                                   withMessage:[containerRequest.userInfo objectForKey:@"failedActivityMessage"]];
             });
-            [objects release];
             objects = nil;
             // Since the server listing failed in all retries, the operation finished and the sync cycle is completeted unsuccesfully
             [self syncOperationFinishedWithSuccess:NO];
                 if (newSyncRequested || syncLate || operation.isCancelled) {
                     [self requestFailed:objectRequest];
                 } else {
-                    __block ASIPithosObjectRequest *newObjectRequest = [PithosUtilities objectBlockDataRequestWithPithos:pithos 
+                    __block ASIPithosObjectRequest *newObjectRequest = [PithosUtilities objectBlockDataRequestWithPithos:pithos
                                                                                                            containerName:pithosContainer.name 
                                                                                                                   object:object 
                                                                                                               blockIndex:missingBlockIndex 
                                         currentBytes:(activity.totalBytes - [missingBlocks count]*pithosContainer.blockSize)];
                 });
 
-                __block ASIPithosObjectRequest *newObjectRequest = [PithosUtilities objectBlockDataRequestWithPithos:pithos 
+                __block ASIPithosObjectRequest *newObjectRequest = [PithosUtilities objectBlockDataRequestWithPithos:pithos
                                                                                                        containerName:pithosContainer.name 
                                                                                                               object:object 
                                                                                                           blockIndex:missingBlockIndex 
                                         currentBytes:currentBytes];
                 });
                 NSUInteger missingBlockIndex = [missingBlocks firstIndex];
-                __block ASIPithosContainerRequest *newContainerRequest = [PithosUtilities updateContainerDataRequestWithPithos:pithos 
+                __block ASIPithosContainerRequest *newContainerRequest = [PithosUtilities updateContainerDataRequestWithPithos:pithos
                                                                                                                  containerName:pithosContainer.name 
                                                                                                                      blockSize:pithosContainer.blockSize 
                                                                                                                        forFile:[objectRequest.userInfo objectForKey:@"filePath"] 
         }
         NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
         if (retries > 0) {
-            ASIPithosRequest *newRequest = (ASIPithosRequest *)[[PithosUtilities copyRequest:request] autorelease];
+            ASIPithosRequest *newRequest = (ASIPithosRequest *)[PithosUtilities copyRequest:request];
             [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
             [networkQueue addOperation:[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]]];
         } else {