Skip to content

Commit 3f7fc19

Browse files
committed
Use explicit item deletion instead of replaceItem & added NSExceptions
1 parent 9a54cdd commit 3f7fc19

File tree

1 file changed

+35
-46
lines changed

1 file changed

+35
-46
lines changed

ios/RNCAsyncStorage.m

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -174,61 +174,50 @@ static dispatch_queue_t RCTGetMethodQueue()
174174
return error ? RCTMakeError(@"Failed to delete storage directory.", error, nil) : nil;
175175
}
176176

177+
178+
NSString *OldStorageDirectory = @"RNCAsyncLocalStorage_V1";
179+
/**
180+
* Creates an NSException used during Storage Directory Migration.
181+
*/
182+
static NSException *RCTStorageDirectionMigrationException(NSString *reason, NSError *error) {
183+
NSMutableString *reasonString = [[NSMutableString alloc] initWithString:reason];
184+
[reasonString appendString:@" - "];
185+
[reasonString appendString:[error description]];
186+
return [[NSException alloc] initWithName:@"RCTStorageDirectoryMigrationFailure" reason:reasonString userInfo:nil];
187+
}
188+
177189
/**
178190
* This check is added to make sure that anyone coming from pre-1.2.2 does not lose cached data.
179191
* Data is migrated from the "RNCAsyncLocalStorage_V1" directory to the "RCTAsyncLocalStorage_V1" directory.
180192
*/
181193
static void RCTStorageDirectoryMigrationCheck() {
182-
NSString *oldStorageDir = RCTCreateStorageDirectoryPath(@"RNCAsyncLocalStorage_V1");
183-
184-
NSError *error;
185-
BOOL isDir;
186-
BOOL oldExists = [[NSFileManager defaultManager] fileExistsAtPath:oldStorageDir isDirectory:&isDir];
187-
188-
// If the old directory exists, it means we need to migrate data to the new directory
189-
if (oldExists && isDir) {
190-
191-
BOOL migrationSuccess;
192-
// If the new storage directory already exists, then this may be caused by ever older data being left behind from previous versions.
193-
// This old data will need to be overwritten.
194-
NSString *newStorageDir = RCTGetStorageDirectory();
195-
BOOL newExists = [[NSFileManager defaultManager] fileExistsAtPath:newStorageDir isDirectory:&isDir];
196-
if (newExists && isDir) {
197-
NSString *backupStorageDir = RCTCreateStorageDirectoryPath(@"RCTBackupAsyncLocalStorage_V1");
198-
// Replace any possible existing data in the new storage with old storage directory
199-
migrationSuccess = [[NSFileManager defaultManager] replaceItemAtURL:[[NSURL alloc] initWithString:newStorageDir]
200-
withItemAtURL:[[NSURL alloc] initWithString:oldStorageDir]
201-
backupItemName:backupStorageDir
202-
options:NSFileManagerItemReplacementUsingNewMetadataOnly
203-
resultingItemURL:nil
204-
error:&error];
205-
if (error || !migrationSuccess) {
206-
// Attempt to recover from failed overwriting
207-
[[NSFileManager defaultManager] removeItemAtPath:newStorageDir error:nil];
208-
[[NSFileManager defaultManager] copyItemAtPath:backupStorageDir toPath:newStorageDir error:nil];
209-
[[NSFileManager defaultManager] removeItemAtPath:backupStorageDir error:nil];
210-
if (error) {
211-
RCTMakeError(@"Failed to overwrite old storage directory to new storage directory location during migration", error, nil);
212-
return;
194+
static dispatch_once_t onceToken;
195+
dispatch_once(&onceToken, ^{
196+
NSError *error;
197+
BOOL isDir;
198+
// If the old directory exists, it means we need to migrate data to the new directory
199+
if ([[NSFileManager defaultManager] fileExistsAtPath:RCTCreateStorageDirectoryPath(OldStorageDirectory) isDirectory:&isDir] && isDir) {
200+
// Check if the new storage directory location already exists
201+
BOOL newStorageDirectoryExists = [[NSFileManager defaultManager] fileExistsAtPath:RCTGetStorageDirectory() isDirectory:&isDir];
202+
if (newStorageDirectoryExists) {
203+
// If the new storage directory location already exists, remove existing directory
204+
newStorageDirectoryExists = !([[NSFileManager defaultManager] removeItemAtPath:RCTGetStorageDirectory() error:&error]);
205+
if (newStorageDirectoryExists) {
206+
@throw RCTStorageDirectionMigrationException(@"Failed to clear pre-existing storage directory", error);
213207
}
214208
}
215-
} else {
216-
// Copy over the old storage directory to new storage directory path
217-
migrationSuccess = [[NSFileManager defaultManager] copyItemAtPath:oldStorageDir toPath:newStorageDir error:&error];
218-
if (error) {
219-
RCTMakeError(@"Failed to copy old storage directory to new storage directory location during migration", error, nil);
220-
return;
221-
}
222-
}
223-
224-
// If the migration was a success, remove old storage directory
225-
if (migrationSuccess) {
226-
[[NSFileManager defaultManager] removeItemAtPath:oldStorageDir error:&error];
227-
if (error) {
228-
RCTMakeError(@"Failed to remove old storage directory after migration", error, nil);
209+
if (!newStorageDirectoryExists) {
210+
// If new storage direction doesn't exist, copy old storage directory to new location
211+
if (![[NSFileManager defaultManager] copyItemAtPath:RCTCreateStorageDirectoryPath(OldStorageDirectory) toPath:RCTGetStorageDirectory() error:&error]) {
212+
@throw RCTStorageDirectionMigrationException(@"Failed to copy old storage directory to new storage directory", error);
213+
} else {
214+
// If copying succeeds, remove old storage directory
215+
[[NSFileManager defaultManager] removeItemAtPath:RCTCreateStorageDirectoryPath(OldStorageDirectory) error:&error];
216+
if (error) @throw RCTStorageDirectionMigrationException(@"Failed to remove old storage directory after migration", error);
217+
}
229218
}
230219
}
231-
}
220+
});
232221
}
233222

234223
#pragma mark - RNCAsyncStorage

0 commit comments

Comments
 (0)