Skip to content

Commit 6355ff1

Browse files
committed
Use explicit item deletion instead of replaceItem & added NSExceptions
1 parent c62ea84 commit 6355ff1

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
@@ -162,61 +162,50 @@ static dispatch_queue_t RCTGetMethodQueue()
162162
return error ? RCTMakeError(@"Failed to delete storage directory.", error, nil) : nil;
163163
}
164164

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

222211
#pragma mark - RNCAsyncStorage

0 commit comments

Comments
 (0)